import numpy as np
import matplotlib.pyplot as plt


def softmax(x):
    val = np.exp(x)
    return val / np.sum(val)


def d_softmax(x):
    """
    np.diagflat() 这个函数的基本用法：传入一个一维数组，输出以该数组为对角线的平铺对角矩阵
    eg:
        arr = np.array([1, 2, 3])
        brr = np.diagflat(arr)
        print(brr.shape)       # (3, 3)
        print(brr)
        [
            [1, 0, 0],
            [0, 2, 0],
            [0, 0, 3]
        ]
    """
    s = softmax(x)
    return np.diagflat(s) - np.outer(s, s)


""" 进行画图 """
x = np.linspace(-5, 5, 100)
y = softmax(x)
dy = d_softmax(x)
plt.subplot(121)
plt.xticks(np.arange(-5, 6, 1))
plt.xlim(-5, 5)
plt.plot(x, y)

plt.subplot(122)
plt.xticks(np.arange(-5, 6, 1))
plt.xlim(-5, 5)
plt.plot(x, dy)

plt.show()

# 一般来说，softmax用在输出之前，隐藏层是不用的
# 将输出值转化为概率 且概率之和为1
label = ["张三", "李四", "王五", "赵六", "张理策"]  # 对应标签
arr = np.array([-1, -2, 0, 1, 2])  # 模拟模型的输出
s = softmax(arr)  # 将输出值转换为概率
print(s)  # [0.03168492 0.01165623 0.08612854 0.23412166 0.63640865]
print(sum(s))  # 1.0
# ？思考：转换为概率之后，我怎么知道对应标签
# 找到最大概率索引idx，然后读取标签label[idx]
print(s.max())  # 返回最大值 0.6364086465588308
print(s.argmax())  # 返回最大值索引下标 4
print(label[s.argmax()])  # 张理策
